package com.qqt.csr.file.service;

import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.IdUtil;
import com.obs.services.exception.ObsException;
import com.qqt.csr.common.utils.CacheKeyUtil;
import com.qqt.csr.common.utils.RedissonLockUtil;
import com.qqt.csr.common.utils.SnowflakeUtil;
import com.qqt.csr.file.dto.MultipartUploadListingDTO;
import com.qqt.csr.file.dto.MultipartUploadTaskDTO;
import jakarta.annotation.PreDestroy;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.MDC;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

@Slf4j
@Component
public class AbortingMultiUploadExpireTaskTimer implements InitializingBean {
    private static final String LOG_TID = "ctid";
    private final ScheduledThreadPoolExecutor executor = ThreadUtil.createScheduledExecutor(1);
    private volatile boolean isShutdown = false;

    @Value("${file.upload.bucketName}")
    private String bucketName;
    @Value("${huawei.obs.multi.upload.expire:86400000}")
    private int expireTime;
    @Autowired
    private RedissonLockUtil redissonLockUtil;
    @Autowired
    private IMultipartFileService multipartFileService;

    @Override
    public void afterPropertiesSet() throws Exception {
        ThreadUtil.schedule(executor,
                () -> {
                    try {
                        MDC.put(LOG_TID, SnowflakeUtil.nextIdStr());
                        redissonLockUtil.distributedLock(this::abort, CacheKeyUtil.File.ABORT_EXPIRE_MULTI_TASK_LOCK);
                    } catch (ObsException e) {
                        log.error("请求oss接口异常!errorCode:{},errorMsg:{}", e.getErrorCode(), e.getErrorMessage());
                    } catch (Throwable e) {
                        log.error("定时取消已过期的分段任务执行异常", e);
                    } finally {
                        MDC.clear();
                    }
                },
                30,
                86400,
                TimeUnit.SECONDS,
                false
        );
    }

    @PreDestroy
    public void destroy() {
        isShutdown = true;
        executor.shutdown();
        log.info("取消过期分段任务定时已关闭");
    }

    private void abort() {
        Date currentDate = new Date();
        String nextKeyMarker = null;
        String nextUploadIdMarker = null;
        MultipartUploadListingDTO listingDTO = null;
        do {
            listingDTO = multipartFileService.listMultipartUploads(bucketName, nextKeyMarker, nextUploadIdMarker, 500);
            for (MultipartUploadTaskDTO taskDTO : listingDTO.getUploadTaskDTOList()) {
                if (taskDTO.getInitiatedDate() == null || StringUtils.isAnyBlank(taskDTO.getObjectKey(), taskDTO.getUploadId())) {
                    log.warn("取消分段任务，查询任务信息异常！taskDTO:{}", taskDTO);
                    continue;
                }
                if (currentDate.getTime() - taskDTO.getInitiatedDate().getTime() > expireTime) {
                    log.info("取消分段任务 bucketName：{}，objectKey：{}，uploadId：{}", bucketName, taskDTO.getObjectKey(), taskDTO.getUploadId());
                    multipartFileService.abortMultipartUpload(bucketName, taskDTO.getObjectKey(), taskDTO.getUploadId());
                }
            }

            nextKeyMarker = listingDTO.getNextKeyMarker();
            nextUploadIdMarker = listingDTO.getNextUploadIdMarker();
        } while (listingDTO.isTruncated() && !isShutdown);
    }


}
